//
//  DWThreadViewController.m
//  OCAPPDemo
//
//  Created by 杨冬武 on 2021/4/26.
//

#import "DWThreadViewController.h"
#import "DWGCDTimer.h"

@interface DWThreadViewController ()

@property (nonatomic, strong) dispatch_queue_t serialQueue;

@property (nonatomic, strong) dispatch_source_t timer;

@property (nonatomic, copy) NSString *timerID;

@end

@implementation DWThreadViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
}

- (IBAction)queue:(id)sender {
    [self testSetTargetQueue];
}

- (void)createQueue {
    //串行队列
    //dispatch_queue_t serialQueue = dispatch_queue_create("name", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t serialQueue = dispatch_queue_create("name", NULL);
    //并发队列
    dispatch_queue_t concurrentQueue = dispatch_queue_create("name", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 10; ++i) {
        dispatch_async(serialQueue, ^{
            NSLog(@"%d", i);
        });
    }
    //    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_queue_t globleQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    
    
//    dispatch_release(serialQueue);
//    dispatch_release(concurrentQueue);
    
}

- (void)testSetTargetQueue {
    
    dispatch_queue_t sQueue1 = dispatch_queue_create("com.gcd.a", NULL);
    dispatch_queue_t sQueue2 = dispatch_queue_create("com.gcd.b", NULL);
    dispatch_queue_t sQueue = dispatch_queue_create("com.gcd.c", NULL);
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_set_target_queue(sQueue1, sQueue);
    dispatch_set_target_queue(sQueue2, sQueue);
    dispatch_async(sQueue1, ^{
        NSLog(@"1");
    });
    dispatch_async(sQueue2, ^{
        NSLog(@"2");
    });
    dispatch_async(sQueue1, ^{
        NSLog(@"3");
    });
    dispatch_async(sQueue2, ^{
        NSLog(@"4");
    });
    
}

#pragma mark - timer

- (IBAction)source:(id)sender {
    
}

- (IBAction)suspendTimer:(id)sender {
    [DWGCDTimer suspendTimerWithID:self.timerID];
}

- (IBAction)resumeTimer:(id)sender {
    [DWGCDTimer resumeTimerWithID:self.timerID];
}

- (IBAction)createTimer:(id)sender {
    self.timerID = [DWGCDTimer executeWithTask:^{
        NSLog(@"timer %@", [NSThread currentThread]);
    } interval:1 delay:0 repeat:YES async:YES cancelHandler:^{
        NSLog(@"cancel");
    }];
}

- (IBAction)cancelTimer:(id)sender {
    [DWGCDTimer cancelTimerWithID:self.timerID];
}

#pragma mark - GCD
- (IBAction)after:(id)sender {
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"after");
    });
    
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)2 * NSEC_PER_SEC);
    
    dispatch_after(time, dispatch_get_main_queue(), ^{
        NSLog(@"%@", @"aaa");
    });
    
    //dispatch_walltime(<#const struct timespec * _Nullable when#>, <#int64_t delta#>)
    
}
- (IBAction)group:(id)sender {
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_async(group, queue, ^{
        sleep(4);
        NSLog(@"0");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"1");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"2");
    });
    
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)2 * NSEC_PER_SEC);
    long result = dispatch_group_wait(group, time);
    if (result) {
        NSLog(@"还在执行中");
    } else {
        NSLog(@"执行完毕");
    }
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"3");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"4");
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"done");
    });
    //dispatch_release(group);
    
}
- (IBAction)barrier:(id)sender {
    
    static int num = 0;
    dispatch_queue_t queue = dispatch_queue_create("com.gcd.barrier", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        sleep(1);
        NSLog(@"num = %d", num);
    });
    dispatch_async(queue, ^{
        NSLog(@"num = %d", num);
    });
    dispatch_async(queue, ^{
        NSLog(@"num = %d", num);
    });
    
    dispatch_barrier_async(queue, ^{
        sleep(1);
        num = 2;
        NSLog(@"dispatch_barrier_async");
    });
    
    NSLog(@"aaa");
    
    dispatch_async(queue, ^{
        sleep(1);
        NSLog(@"num = %d", num);
    });
    
//    dispatch_barrier_async_and_wait(queue, ^{
//
//    });
    
//    dispatch_barrier_sync(queue, ^{
//        //NSLog(@"num = %d", num);
//        num = 3;
//        sleep(1);
//        NSLog(@"dispatch_barrier_async_and_wait");
//    });
    
    NSLog(@"bbb");
    
    dispatch_async(queue, ^{
        NSLog(@"num = %d", num);
    });
    dispatch_async(queue, ^{
        NSLog(@"num = %d", num);
    });
}
- (IBAction)async:(id)sender {
    
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_queue_t serialQueue = dispatch_queue_create("com.gcd.se", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.gcd.async", DISPATCH_QUEUE_CONCURRENT);
    
    //开启新的线程,并发执行
    
    dispatch_async(concurrentQueue, ^{
        //sleep(1);
        NSLog(@"dispatch_async concurrent 0 %@", [NSThread currentThread]);
    });
    dispatch_async(concurrentQueue, ^{
        //sleep(1);
        NSLog(@"dispatch_async concurrent 1 %@", [NSThread currentThread]);
    });
    dispatch_async(concurrentQueue, ^{
        //sleep(1);
        NSLog(@"dispatch_async concurrent 2 %@", [NSThread currentThread]);
    });
     
    
    
    //主线程,串行执行
    
    dispatch_async(mainQueue, ^{
        NSLog(@"dispatch_async Main 0 %@", [NSThread currentThread]);
    });
    dispatch_async(mainQueue, ^{
        NSLog(@"dispatch_async Main 1 %@", [NSThread currentThread]);
    });
    dispatch_async(mainQueue, ^{
        NSLog(@"dispatch_async Main 2 %@", [NSThread currentThread]);
    });
     
    
    //开启新的线程,串行执行,三次共用一个线程 (和上一次线程可能相同,怀疑和线程池有关)
    
    dispatch_async(serialQueue, ^{
        NSLog(@"dispatch_async serial 0 %@", [NSThread currentThread]);
    });
    dispatch_async(serialQueue, ^{
        NSLog(@"dispatch_async serial 1 %@", [NSThread currentThread]);
    });
    dispatch_async(serialQueue, ^{
        NSLog(@"dispatch_async serial 2 %@", [NSThread currentThread]);
    });
    
    
}
- (IBAction)sync:(id)sender {
    
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_queue_t serialQueue = dispatch_queue_create("com.gcd.async.serial", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.gcd.async.concurrent", DISPATCH_QUEUE_CONCURRENT);
    
    
    //不开启新的线程,串行执行任务
    
    /*
    dispatch_sync(concurrentQueue, ^{
        //sleep(1);
        NSLog(@"dispatch_sync concurrent 0 %@", [NSThread currentThread]);
    });
    dispatch_sync(concurrentQueue, ^{
        //sleep(1);
        NSLog(@"dispatch_sync concurrent 1 %@", [NSThread currentThread]);
    });
    dispatch_sync(concurrentQueue, ^{
        //sleep(1);
        NSLog(@"dispatch_sync concurrent 2 %@", [NSThread currentThread]);
    });
     */
    
    /*
     主线程不允许添加同步任务,会产生死锁.
     dispatch_sync(mainQueue, ^{
     NSLog(@"dispatch_sync Main 0 %@", [NSThread currentThread]);
     });
     */
    
    //死锁
    /*
     使用同步方式向串行队列添加任务会阻塞队列(死锁).
     NSLog(@"1");
     dispatch_async(serialQueue, ^{
     NSLog(@"2");
     
     dispatch_async_and_wait(serialQueue, ^{
     
     });
     
     dispatch_sync(serialQueue, ^{
     NSLog(@"3");
     // outer block is waiting for this inner block to complete,
     // inner block won't start before outer block finishes
     // => deadlock
     NSLog(@"dispatch_sync serial 0 %@", [NSThread currentThread]);
     });
     NSLog(@"4");
     });
     NSLog(@"5");
    */
    
    NSLog(@"%@", [NSThread currentThread]);
    /*
    dispatch_sync(serialQueue, ^{
        NSLog(@"dispatch_sync serial 1 %@", [NSThread currentThread]);
        dispatch_sync(serialQueue, ^{
            
        });
    });
    */
    
    
    /*
    dispatch_async(serialQueue, ^{
        //串行队列添加一个同步串行任务(死锁)
        dispatch_sync(serialQueue, ^{
            NSLog(@"dispatch_sync serial 2 %@", [NSThread currentThread]);
        });
    });
     */
    NSLog(@"a: %@", [NSThread currentThread]);
    
    
}
- (IBAction)apply:(id)sender {
    
    NSArray *arr = @[@1, @2, @3, @4];
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.gcd.apply.concurrent", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t serialQueue = dispatch_queue_create("com.gcd.apply.serail", NULL);
    NSLog(@"start");
    dispatch_async(concurrentQueue, ^{
        //由于dispatch_apply会阻塞,所以最好异步执行
        dispatch_apply(arr.count, concurrentQueue, ^(size_t index) {
            sleep(arc4random_uniform(3));
            NSLog(@"%@-%@", arr[index], [NSThread currentThread]);
        });
    });
    NSLog(@"end");
    
}
- (void)createDispatchSerailQueueAndBlock {
    self.serialQueue = dispatch_queue_create("com.gcd.serail", NULL);
    for (int i = 0; i < 10; i++) {
        dispatch_async(self.serialQueue, ^{
            sleep(1);
            NSLog(@"111");
        });
    }
}
- (IBAction)suspend:(id)sender {
    dispatch_suspend(self.serialQueue);
}
- (IBAction)resume:(id)sender {
    dispatch_resume(self.serialQueue);
}
- (IBAction)semaphore:(id)sender {
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    dispatch_queue_t globleQueue = dispatch_get_global_queue(0, 0);
    NSMutableArray *array = [[NSMutableArray alloc] init];
    for (int i = 0; i < 100; i++) {
        dispatch_async(globleQueue, ^{
            
            dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC));
            long result = dispatch_semaphore_wait(semaphore, time);
            if (result == 0) {
                //semaphore 计数值大于等于1
                [array addObject:[NSNumber numberWithInt:i]];
            } else {
                //semaphore 计数值等于0 等待时间到了
            }
            
            NSLog(@"%d", i);
            
            dispatch_semaphore_signal(semaphore);
        });
    }
    
}

#pragma mark - 网络依赖
- (IBAction)netDependGroup:(id)sender {
    
    dispatch_queue_t dispatchQueue = dispatch_queue_create("com.ydw.net", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
    dispatch_group_enter(group);
    dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    NSLog(@"请求任务一开始");
    dispatch_async(global, ^{
        sleep(3);
        NSLog(@"请求任务一完成");
        dispatch_group_leave(group);
    });
    
    dispatch_group_async(group, dispatchQueue, ^{
        
        NSLog(@"请求任务二开始");
        dispatch_async(global, ^{
            sleep(5);
            NSLog(@"请求任务二完成");
            dispatch_semaphore_signal(semaphore);
        });
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
    });
    
    dispatch_group_enter(group);
    NSLog(@"请求任务三开始");
    dispatch_async(global, ^{
        sleep(5);
        NSLog(@"请求任务三完成");
        dispatch_group_leave(group);
    });
    
    //    dispatch_group_async(group, dispatchQueue, ^{
    //    });
    
    dispatch_group_notify(group, dispatchQueue, ^{
        NSLog(@"请求任务四开始");
    });
}


@end
